package com.anlogic.sdk.bsp.settings;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ITableColorProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Tree;

public class Config {
	private TreeViewer viewer;

	private IBspSettingTool bspSettingTool;

	private String component;

	private String comptype;

	private PropertyProvider propertyProvider;

	private PropertyValueEditingSupport editingSupport;

	private IProperty propertyRoot;

	private Map<String, IProperty> properties;

	public Config(TreeViewer viewer, String component, String comptype, IBspSettingTool bspSettingTool) {
		this.viewer = viewer;
		this.bspSettingTool = bspSettingTool;
		this.component = component;
		this.comptype = comptype;
		this.propertyProvider = new PropertyProvider();
		createConfigItems();
		this.editingSupport = new PropertyValueEditingSupport((ColumnViewer) this.viewer);
	}

	public String getType() {
		return this.comptype;
	}

	public Map<String, IProperty> getProperties() {
		return this.properties;
	}

	public IProperty getConfigRoot() {
		return this.propertyRoot;
	}

	public ITreeContentProvider getContentProvider() {
		return this.propertyProvider;
	}

	public ITableLabelProvider getLabelProvider() {
		return this.propertyProvider;
	}

	public EditingSupport getEditingSupport() {
		return this.editingSupport;
	}

	private void createConfigItems() {
		this.properties = this.bspSettingTool.getProperties(this.component, this.comptype);
		boolean isFirst = true;
		for (IProperty prop : this.properties.values()) {
			if (isFirst) {
				this.propertyRoot = prop.getParent();
				isFirst = false;
			}
			for (IProperty p : prop.getChildren()) {
				if (!prop.getIsEditable() || prop.getValue().equals("false")) {
					p.setIsEditable(false);
				} else {
					p.setIsEditable(true);
				}
			}
		}
	}

	class PropertyProvider extends LabelProvider
			implements ITreeContentProvider, ITableColorProvider, ITableLabelProvider {
		public Object[] getChildren(Object element) {
			if (!(element instanceof IProperty))
				return new Object[0];
			IProperty n = (IProperty) element;
			return n.getChildren().toArray((Object[]) new IProperty[0]);
		}

		public Object getParent(Object element) {
			if (!(element instanceof IProperty))
				return null;
			IProperty n = (IProperty) element;
			return n.getParent();
		}

		public boolean hasChildren(Object element) {
			if (!(element instanceof IProperty))
				return false;
			IProperty n = (IProperty) element;
			return (n.getChildren().size() != 0);
		}

		public Object[] getElements(Object element) {
			return getChildren(element);
		}

		public void dispose() {
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}

		public String getText(Object element) {
			if (!(element instanceof IProperty))
				return "";
			IProperty n = (IProperty) element;
			return n.getName();
		}

		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		public String getColumnText(Object element, int columnIndex) {
			if (!(element instanceof IProperty))
				return "";
			IProperty c = (IProperty) element;
			switch (columnIndex) {
			case 0:
				return c.getName();
			case 1:
				return c.getValue();
			case 2:
				return c.getDefaultValue();
			case 3:
				return c.getTypeAsString();
			case 4:
				return c.getDesc();
			}
			return "";
		}

		public Color getBackground(Object element, int columnIndex) {
			return null;
		}

		public Color getForeground(Object element, int columnIndex) {
			if (!(element instanceof IProperty))
				return null;
			if (columnIndex != 0 && columnIndex != 1)
				return null;
			IProperty p = (IProperty) element;
			Color gray = new Color(null, 150, 150, 150);
			if (!p.getIsEditable())
				return gray;
			if (!p.getPermit() && columnIndex == 1)
				return gray;
			if (p.isCategory() && p.getValue().equals("false") && columnIndex == 0)
				return gray;
			return null;
		}
	}

	class PropertyValueEditingSupport extends EditingSupport {
		private Map<String, CellEditor> editorMap = new HashMap<String, CellEditor>();

		private ColumnViewer viewer;

		public PropertyValueEditingSupport(ColumnViewer viewer) {
			super(viewer);
			TreeViewer treeView = (TreeViewer) viewer;
			Tree tree = treeView.getTree();
			for (IProperty prop : properties.values()) {
				int propType = prop.getType();
				if (propType == IProperty.TYPE_BOOLEAN || propType == IProperty.TYPE_ARRAY) {
					ComboBoxCellEditor editor = new ComboBoxCellEditor((Composite) tree, prop.getValueOptions(), 8);
					this.editorMap.put(prop.getName(), editor);
				} else if (propType == IProperty.TYPE_INTEGER || propType == IProperty.TYPE_STRING) {
					TextCellEditor editor = new TextCellEditor((Composite) tree, 0);
					this.editorMap.put(prop.getName(), editor);
				}
				for(IProperty p : prop.getChildren()) {
					propType = p.getType();
					if (propType == IProperty.TYPE_BOOLEAN || propType == IProperty.TYPE_ARRAY) {
						ComboBoxCellEditor editor = new ComboBoxCellEditor((Composite) tree, p.getValueOptions(), 8);
						this.editorMap.put(p.getName(), editor);
					} else if (propType == IProperty.TYPE_INTEGER || propType == IProperty.TYPE_STRING) {
						TextCellEditor editor = new TextCellEditor((Composite) tree, 0);
						this.editorMap.put(p.getName(), editor);
					}
				}
			}
			this.viewer = viewer;
		}

		protected boolean canEdit(Object element) {
			if (!(element instanceof IProperty))
				return true;
			IProperty p = (IProperty) element;
			if (!p.getIsEditable() || !p.getPermit())
				return false;
			return true;
		}

		protected CellEditor getCellEditor(Object element) {
			if (!(element instanceof IProperty))
				return null;
			IProperty p = (IProperty) element;
			return this.editorMap.get(p.getName());
		}

		protected Object getValue(Object element) {
			if (!(element instanceof IProperty))
				return null;
			IProperty c = (IProperty) element;
			if (c.getType() == IProperty.TYPE_BOOLEAN || c.getType() == IProperty.TYPE_ARRAY)
				return Integer.valueOf(c.getIndexOfValue());
			return c.getValue();
		}

		protected void setValue(Object element, Object value) {
			if (!(element instanceof IProperty))
				return;
			if (value == null || value == "")
				return;
			boolean refreshChildren = false;
			IProperty p = (IProperty) element;
			if (p.getType() == IProperty.TYPE_BOOLEAN || p.getType() == IProperty.TYPE_ARRAY) {
				Integer i = (Integer) value;
				if (i.intValue() >= 0)
					p.setValue(p.getValueOptions()[i.intValue()]);
				if (p.getType() == 1 && p.isCategory()) {
					for (IProperty c : p.getChildren()) {
						if (p.getValue().equals("true")) {
							c.setIsEditable(true);
							continue;
						}
						c.setIsEditable(false);
					}
					refreshChildren = true;
				}
			} else {
				p.setValue((String) value);
			}
			this.viewer.refresh(p);
			if (refreshChildren)
				for (IProperty c : p.getChildren())
					this.viewer.refresh(c);
		}
	}
}
